package kr.or.javacafe.news.service;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import kr.or.javacafe.demo.domain.mongo.TwitterWord;
import kr.or.javacafe.news.domain.GoogleNews;
import kr.or.javacafe.news.domain.NewsWordCount;
import kr.or.javacafe.news.domain.rss.Rss;
import kr.or.javacafe.news.domain.rss.RssChannelItem;
import kr.or.javacafe.news.repository.NewsRepository;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.xml.sax.InputSource;




@Service
public class NewsService {

	static Logger logger = LoggerFactory.getLogger(NewsService.class);

	@Autowired
	NewsRepository newsRepository;
	

	public List<GoogleNews> getGoogleNewsUsingRSS() {
		
		List<GoogleNews> objList = new ArrayList<GoogleNews>();

		String strXML = this.getXML("http://news.google.co.kr/news?ned=kr&output=rss");
		if (StringUtils.isNotEmpty(strXML)) {
			
			try {
				JAXBContext context = JAXBContext.newInstance(Rss.class);
				Unmarshaller ums = context.createUnmarshaller();

				Rss objRss = (Rss)ums.unmarshal(new InputSource(new StringReader(strXML)));
				
				for (RssChannelItem item : objRss.getChannel().getItems()) {
					
					GoogleNews gNews = new GoogleNews();
					
					gNews.setGuid(item.getGuid());
					gNews.setTitle(this.splitNewsTitle(item.getTitle()));
					gNews.setPubName(this.splitNewsPubName(item.getTitle()));
					gNews.setPubDate(this.convertTimeFormat(item.getPubDate()));
					gNews.setLink(item.getLink());
					gNews.setIsHadoop("N");
					
					objList.add(gNews);
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}

		return objList;
	}

	
	private String getXML(String strURL) {
	
		String strXML = "";
		
		try {
			HttpClient httpClient = new HttpClient();
			HttpMethod method = new GetMethod(strURL);
			
			int status = httpClient.executeMethod(method);
			if (200 == status) {
	            StringBuilder resultHtml = new StringBuilder();
	            InputStreamReader isr = new InputStreamReader(method.getResponseBodyAsStream(), "UTF-8");
	
	            int isrRead = -1;
	
	            while ((isrRead = isr.read()) != -1) {
	                resultHtml.append((char)isrRead);
	            }
	
	            isr.close();
	
	            strXML = resultHtml.toString();
				
				logger.debug("======================================================================================");
				logger.debug(strXML);
				logger.debug("======================================================================================");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return strXML;
	}
		
	
	private String splitNewsPubName(String strText) {
		
		try {
			String[] arrTemp = strText.split(" ");
			
			return arrTemp[arrTemp.length-1].trim();
		
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		
		return "Fail";
	}
	
	
	private String splitNewsTitle(String strText) {
		
		try {
			String[] arrTemp = strText.split(" ");
			strText = strText.replace("- " + arrTemp[arrTemp.length-1], "");
		
			return strText.trim();
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		
		return strText;
	}
	
	private String convertTimeFormat(String strText) {
		SimpleDateFormat sdFormat1 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
		SimpleDateFormat sdFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		ParsePosition pos = new ParsePosition(0);
		Date objDate = sdFormat1.parse(strText, pos);
		
		return sdFormat2.format(objDate);
	}
	
	
	public void saveGoogleNews(List<GoogleNews> objList) {
		for (GoogleNews obj : objList) {
			
			Query query = new Query();
			query.addCriteria(Criteria.where("link").is(obj.getLink()));
			query.limit(1);
			
			GoogleNews objTemp = newsRepository.selectGoogleNews(query);
			if (objTemp == null) {
				newsRepository.insertGoogleNews(obj);				
			}
			
		}
	}
	
	
	public List<GoogleNews> findAllGoogleNews() {
		Query query = new Query();
		query.with(new Sort(Sort.Direction.DESC, "pubDate"));
		query.limit(100);
		
		return newsRepository.selectGoogleNewsAllList(query);
	}
	
	
	public List<GoogleNews> findGoogleNews(String word) {
		Query query = new Query();
		query.addCriteria(Criteria.where("title").regex(word));
		query.with(new Sort(Sort.Direction.DESC, "pubDate"));
		query.limit(100);
		
		return newsRepository.selectGoogleNewsAllList(query);
	}

	
	public long findGoogleNewsCount() {
		return newsRepository.selectGoogleNewsCount();
	}
	
	
	public void getWordCountUsingHadoop(String path) {		
		String strLine = "";
		
		try {
			FileReader fr = new FileReader(path);
			BufferedReader br = new BufferedReader(fr);
			
			String[] arrTemp;
			NewsWordCount wc = new NewsWordCount();
			
			int i=1;
			while ((strLine = br.readLine()) != null) {
				if (i%100 == 0) {
					System.out.println(". " + i);
				} else {
					System.out.print(".");
				}
				
				try {
					arrTemp = strLine.split("\\t");

					wc = new NewsWordCount();
					wc.setWord(arrTemp[0].trim());
					wc.setCount(arrTemp[1].trim());
					
					newsRepository.insertNewsWordCount(wc);
					
				} catch (Exception ex) {
					//ex.printStackTrace();
					System.out.println("Line No [" + i + "] " + strLine);
					System.out.println(ex.getMessage());
				}
				
				i++;
			}
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
	
	
	
	public long getNewsWordTotalCount() {
		return newsRepository.selectWordCountCount();
	}
	
	public List<NewsWordCount> findBestNewsWord() {
		Query query = new Query();
		query.with(new Sort(Sort.Direction.DESC, "count"));
		query.limit(5);
		
		return newsRepository.selectWordCount(query);
	}
	
	public List<NewsWordCount> findNewsWord() {
		Query query = new Query();
		query.with(new Sort(Sort.Direction.DESC, "count"));
		query.limit(100);
		
		return newsRepository.selectWordCount(query);
	}
	
	public List<NewsWordCount> findNewsWord(String word) {
		Query query = new Query();
		query.addCriteria(Criteria.where("word").regex(word));
		query.with(new Sort(Sort.Direction.DESC, "count"));
		query.limit(100);
		
		return newsRepository.selectWordCount(query);
	}
	
	
}
























